package com.bootdo.payee.service.impl;

import static com.bootdo.common.utils.ShiroUtils.getUserId;

import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.bootdo.common.config.Constant;
import com.bootdo.common.redis.lock.CommonRedisLock;
import com.bootdo.common.utils.DateUtils;
import com.bootdo.common.utils.MD5Utils;
import com.bootdo.common.utils.StringUtils;
import com.bootdo.mq.RabbitUtil;
import com.bootdo.mq.SendSortUtil;
import com.bootdo.payee.dao.PayeeAgentDao;
import com.bootdo.payee.dao.PayeeDao;
import com.bootdo.payee.dao.PaymentCodeDao;
import com.bootdo.payee.domain.PayeeAgentDO;
import com.bootdo.payee.domain.PayeeDO;
import com.bootdo.payee.domain.PaymentCodeDO;
import com.bootdo.payee.service.PayeeService;
import com.bootdo.quota.dao.QuotaDao;
import com.bootdo.quota.dao.QuotaHistoryDao;
import com.bootdo.quota.domain.QuotaDO;
import com.bootdo.quota.domain.QuotaHistoryDO;
import com.bootdo.rate.dao.RateDao;
import com.bootdo.rate.domain.RateDO;
import com.bootdo.system.dao.UserDao;
import com.bootdo.system.dao.UserRoleDao;
import com.bootdo.system.domain.UserDO;
import com.bootdo.system.domain.UserRoleDO;

@Service
public class PayeeServiceImpl implements PayeeService{

    @Autowired
    private PayeeDao payeeMapper;
    @Autowired
    private UserDao userMapper;
    @Autowired
    private UserRoleDao userRoleMapper;
    @Autowired
    private RateDao rateMapper;
    @Autowired
    private QuotaDao quotaMapper;
    @Autowired
    private PayeeAgentDao payeeAgentMapper;
    @Autowired
    private RabbitUtil rabbitUtil;
    @Autowired
    private QuotaHistoryDao quotaHistoryMapper;
    @Autowired
    private PaymentCodeDao paymentCodeMapper;
    @Autowired
    protected StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SendSortUtil sendSortUtil;


    @Override
    public List<PayeeAgentDO> findAgent(){
        int checkUserIsManager = userRoleMapper.checkUserIsManager(getUserId());
        if (checkUserIsManager != 1){
            return null;
        }
        return payeeAgentMapper.list(new HashMap<>());
    }

    /**
     * 获取收款户列表
     * @param map
     * @return
     */
    @Override
    public List<PayeeDO> list(Map<String, Object> map){
        //获取用户权限
        int checkUserIsManager = userRoleMapper.checkUserIsManager(getUserId());
        if (checkUserIsManager != 1){
            map.put("userIdCreate", getUserId());
        }
        return payeeMapper.list(map);
    }

    /**
     * 获取收款户列表总条数
     * @param map
     * @return
     */
    @Override
    public int count(Map<String, Object> map){
        return payeeMapper.count(map);
    }

    /**
     * 新增收款户
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int save(PayeeDO payee){
        payee.setUserName(payee.getUserName().trim());
        payee.setName(payee.getName().trim());
        //添加用户表
        UserDO userDO = new UserDO();
        userDO.setUsername(payee.getUserName());
        userDO.setPassword(payee.getPassword());
        userDO.setStatus(1);
        userDO.setMobile(payee.getMobile());
        userMapper.save(userDO);
        Long userId = userDO.getUserId();
        userRoleMapper.removeByUserId(userId);
        UserRoleDO ur = new UserRoleDO();
        ur.setUserId(userId);
        ur.setRoleId(63L);
        userRoleMapper.save(ur);

        payee.setUserId(userId);
        payee.setGmtCreate(new Date());
        payee.setLineUpStatus(0);

        //新增收款户时 添加该通道
        String queueName = "topic.payee.user_"+userId;
        Queue queue = new Queue(queueName,true);
        rabbitUtil.addQueue(queue);

        int count = payeeMapper.save(payee);

        //设置额度
        QuotaDO quota = new QuotaDO();
        quota.setUserId(userId);
        quota.setActualQuota(payee.getQuota() == null ? 0.00 : payee.getQuota());
        quota.setChangeReason("初始额度");
        quota.setStatus(1);
        quota.setQuota(payee.getQuota() == null ? 0.00 : payee.getQuota());
        quota.setChangeType(0);
        quota.setGmtDate(new Date());
        quotaMapper.save(quota);
        //插入历史表
        QuotaHistoryDO quotaHistory = new QuotaHistoryDO();
        quotaHistory.setUserId(userId);
        quotaHistory.setQuota(payee.getQuota() == null ? 0.00 : payee.getQuota());
        quotaHistory.setActualQuota(payee.getQuota() == null ? 0.00 : payee.getQuota());
        quotaHistory.setChangeReason("初始额度");
        quotaHistory.setStatus(1);
        quotaHistory.setChangeType(0);
        quotaHistory.setGmtDate(new Date());
        quotaHistory.setVersion(1);
        quotaHistoryMapper.save(quotaHistory);

        return count;
    }

    @Override
    public PayeeDO get(Long userId){
        PayeeDO payee = payeeMapper.get(userId);
        QuotaDO quota = quotaMapper.get(userId);
        //用户实际额度
        payee.setQuota(quota.getActualQuota());
        RateDO rate = rateMapper.getRate(payee.getUserId(), 0);
        if (rate != null){
            payee.setWeixinFixedRate(rate.getWeixinFixedRate());
            payee.setAlipayFixedRate(rate.getAlipayFixedRate());
            payee.setAlipayTransferRate(rate.getAlipayTransferRate());
            payee.setAlipayAccountTransRate(rate.getAlipayAccountTransRate());
        }
        return payee;
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int update(PayeeDO payee){
        if (StringUtils.isNotBlank(payee.getUserName())){
            payee.setUserName(payee.getUserName().trim());
        }
        if (StringUtils.isNotBlank(payee.getName())){
            payee.setName(payee.getName().trim());
        }
        String password = payee.getPassword();
        PayeeDO payeetDO = payeeMapper.get(payee.getUserId());
        if (StringUtils.isBlank(password) || password.equals(payeetDO.getPassword())){
            payee.setPassword(null);
        } else {
            payee.setPassword(MD5Utils.encrypt(payeetDO.getUserName(), password));
            UserDO user = new UserDO();
            user.setUserId(payee.getUserId());
            user.setPassword(payee.getPassword());
            userMapper.update(user);
        }

        int count = payeeMapper.update(payee);

        //修改用户状态
        if (payee.getStatus() != null) {
            UserDO user = new UserDO();
            user.setUserId(payee.getUserId());
            user.setStatus(payee.getStatus());
            userMapper.update(user);
        }

        //修改额度
        QuotaDO quota = quotaMapper.get(payee.getUserId());
        if (payee.getQuota() != null && payee.getQuota().doubleValue() != quota.getActualQuota().doubleValue()){
            String reason = "平台调整";
            //获取用户权限
            int checkUserIsManager = userRoleMapper.checkUserIsManager(getUserId());
            if (checkUserIsManager != 1){
                reason = "代理调整";
            }

            JSONObject object = new JSONObject();
            object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
            object.put("userId", payee.getUserId());
            object.put("money",payee.getQuota());
            object.put("orderId", "");
            if (payee.getQuota().doubleValue() > quota.getActualQuota().doubleValue()){
                object.put("reason", reason + "增加");
                object.put("type", 1);
            } else {
                object.put("reason", reason + "减少");
                object.put("type", 2);
            }
            rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());
        }
        return count;
    }

    /**
     * 收款户状态修改
     * @param userId
     * @param status
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int editStatus(Long userId, Integer status){
        PayeeDO payee = payeeMapper.get(userId);
        //获取上级状态
        UserDO users = userMapper.get(payee.getUserIdCreate());
        if (users.getStatus() == 0){
            return 0;
        }
        payee.setGmtModified(new Date());
        payee.setStatus(status);
        payee.setLineUpStatus(0);
        int count = payeeMapper.update(payee);

        //修改用户状态
        UserDO user = new UserDO();
        user.setUserId(payee.getUserId());
        user.setStatus(payee.getStatus());
        userMapper.update(user);

        //根据用户排队通道以及userId获取用户是否存在排队
        PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(payee.getUserId());
        if (paymentCode != null){
            CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
            boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(payee.getUserId()));
            if (f){
                commonRedisLock.lRemove(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), 0, String.valueOf(payee.getUserId()));
                JSONObject object = new JSONObject();
                String queueName = Constant.QUEUE_START+payee.getUserId();
                object.put("code",3);
                object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
                object.put("userId",payee.getUserId());
                object.put("msg","当前用户已被禁用，请联系管理员");
                object.put("payType",paymentCode.getPassagewayId());
                rabbitUtil.sendToQueue(queueName,object.toJSONString());
            }
            //推送排队信息
            sendSortUtil.sendMsg(paymentCode.getPassagewayId());
        }
        return count;
    }

    @Override
    public int editLineUpStatus(Long userId, Integer status) {
        PayeeDO payee = new PayeeDO();
        payee.setUserId(userId);
        payee.setGmtModified(new Date());
        payee.setLineUpStatus(0);
        payee.setLineStatus(status);
        //当用户接单状态为禁用状态则退出排队
        PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(payee.getUserId());
        if(paymentCode != null){
            CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
            boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(payee.getUserId()));
            if (f){
                commonRedisLock.lRemove(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), 0, String.valueOf(payee.getUserId()));
                JSONObject object = new JSONObject();
                String queueName = Constant.QUEUE_START+payee.getUserId();
                object.put("code",3);
                object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
                object.put("userId",payee.getUserId());
                object.put("msg","当前用户已被禁用接单，请联系管理员");
                object.put("payType",paymentCode.getPassagewayId());
                rabbitUtil.sendToQueue(queueName,object.toJSONString());
            }
            //推送排队信息
            sendSortUtil.sendMsg(paymentCode.getPassagewayId());
        }
        return payeeMapper.update(payee);
    }

    @Override
    public List<PayeeAgentDO> queryPayeeAgentList(){
        Long userId = null;
        int i = userRoleMapper.checkUserIsManager(getUserId());
        if (1 != i){
            userId = getUserId();
        }
        return payeeAgentMapper.queryPayeeAgentList(userId);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int deviceSave(Long userId){
        PayeeDO payee = payeeMapper.get(userId);
        return payeeMapper.updateDevice(payee);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int batchEditStatus(Long[] ids){
        //根据第一位状态判断下面所有状态
        int count = 0;
        PayeeDO payee = payeeMapper.get(ids[0]);
        Set<Integer> set = new CopyOnWriteArraySet<>();
        if (0 == payee.getStatus().intValue()){
            count = payeeMapper.batchEditStatusYes(ids);
        } else if (1 == payee.getStatus().intValue()){
            count = payeeMapper.batchEditStatusNo(ids);
            CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
            for (Long userId : ids){
                //当用户接单状态为禁用状态则退出排队
                PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(userId);
                if (paymentCode != null) {
                    boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(userId));
                    if (f){
                        set.add(paymentCode.getPassagewayId());
                        commonRedisLock.lRemove(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), 0, String.valueOf(userId));
                        JSONObject object = new JSONObject();
                        String queueName = Constant.QUEUE_START+payee.getUserId();
                        object.put("code",3);
                        object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
                        object.put("userId",payee.getUserId());
                        object.put("msg","当前用户已被禁用，请联系管理员");
                        object.put("payType", paymentCode.getPassagewayId());
                        rabbitUtil.sendToQueue(queueName,object.toJSONString());
                    }
                }
            }
            //推送排队信息
            sendSortUtil.sendMsg(set);
        } else {
            count = -1;
        }
        return count;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public int batchEditLineUpStatus(Long[] ids){
        //根据第一位状态判断下面所有状态
        int count = 0;
        PayeeDO payee = payeeMapper.get(ids[0]);
        Set<Integer> set = new CopyOnWriteArraySet<>();
        if (0 == payee.getLineStatus().intValue()) {
            count = payeeMapper.batchEditLineUpStatusYes(ids);
        } else if (1 == payee.getLineStatus().intValue()){
            count = payeeMapper.batchEditLineUpStatusNo(ids);
            CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
            for (Long userId : ids){
                //当用户接单状态为禁用状态则退出排队
                PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(userId);
                if (paymentCode != null) {
                    boolean f = commonRedisLock.searchListByValue(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(userId));
                    if (f){
                        set.add(paymentCode.getPassagewayId());
                        commonRedisLock.lRemove(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), 0, String.valueOf(userId));
                        JSONObject object = new JSONObject();
                        String queueName = Constant.QUEUE_START+payee.getUserId();
                        object.put("code",3);
                        object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
                        object.put("userId",payee.getUserId());
                        object.put("msg","当前用户已被禁用接单，请联系管理员");
                        object.put("payType", paymentCode.getPassagewayId());
                        rabbitUtil.sendToQueue(queueName,object.toJSONString());
                    }
                }
            }
            //推送排队信息
            sendSortUtil.sendMsg(set);
        } else {
            count = -1;
        }
        return count;
    }
}
